package com.gezi.admin.utils.excel;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;

import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * https://dhexx.cn/news/show-5075806.html?action=onClick
 *
 * @Author 格子软件
 * @createDate 2024/2/10 09:00
 * @contact 公众号：格子软件 微信：13716343106 邮箱：1424529270@qq.com
 */
@Slf4j
public class GzExcelUtil<T> {

    /**
     * 实体对象
     */
    public Class<T> clazz;

    /**
     * 字段注解列表
     */
    private List<Pair<String, ExcelColumn>> fieldColumnList = CollUtil.newArrayList();

    private ExcelWriter excelWriter;

    private ExcelTable excelTable;

    public GzExcelUtil(Class<T> clazz) {
        this.clazz = clazz;
    }

    public static void main(String[] args) {
//        GzExcelUtil<ExcelTestModel> gzExcelUtil = new GzExcelUtil<>(ExcelTestModel.class);
//        List<ExcelTestModel> list = CollUtil.newArrayList();
//        list.add(new ExcelTestModel("闫伟1", "男", 12));
//        list.add(new ExcelTestModel("闫伟2", "女", 13));
//        list.add(new ExcelTestModel("闫伟3", "女", 14));
//        list.add(new ExcelTestModel("闫伟4", "女", 15));
//        list.add(new ExcelTestModel("闫伟5", "女", 15));
//        list.add(new ExcelTestModel("闫伟6", "女", 15));
//        list.add(new ExcelTestModel("闫伟7", "女", 15));
//        list.add(new ExcelTestModel("闫伟8", "女", 15));
//        list.add(new ExcelTestModel("闫伟2", "女", 15));
//        list.add(new ExcelTestModel("闫伟2", "女", 15));
//        list.add(new ExcelTestModel("闫伟2", "女", 15));
//        list.add(new ExcelTestModel("闫伟2", "女", 15));
        List<Map> list = CollUtil.newArrayList();
        list.add(MapUtil.builder().put("name","闫伟").put("sex","女").put("age",12).build());
        list.add(MapUtil.builder().put("name","闫伟1").put("sex","女").put("age",11).build());
        list.add(MapUtil.builder().put("name","闫伟2").put("sex","女").put("age",12).build());
        list.add(MapUtil.builder().put("name","闫伟3").put("sex","女").put("age",13).build());
        list.add(MapUtil.builder().put("name","闫伟4").put("sex","女").put("age",14).build());
        list.add(MapUtil.builder().put("name","闫伟5").put("sex","女").put("age",15).build());
        list.add(MapUtil.builder().put("name","闫伟6").put("sex","女").put("age",16).build());
        list.add(MapUtil.builder().put("name","闫伟7").put("sex","女").put("age",17).build());
        list.add(MapUtil.builder().put("name","闫伟8").put("sex","女").put("age",18).build());
        list.add(MapUtil.builder().put("name","闫伟9").put("sex","女").put("age",19).build());

        GzExcelUtil<Map> gzExcelUtil = new GzExcelUtil(ExcelTestModel.class);
        gzExcelUtil.exportExcel(list, "闫伟测试", Arrays.asList("name", "sex", "age"));
    }

    /**
     * 对list数据源将其里面的数据导入到excel表单
     *
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     * @return 结果
     */
    public void exportExcel(List<T> list, String sheetName, List<String> useFieldList) {
        this.excelWriter = cn.hutool.poi.excel.ExcelUtil.getWriter("D:/YanWe/Desktop/新建文件夹/" + DateUtil.format(DateUtil.date(), "HHmmss") + ".xlsx");
        excelWriter.renameSheet(sheetName);

        //初始化参数
        initData(useFieldList);
        //设置标题
//        setTitle(sheetName);
        //设置头部
        setHeader();
        //设置数据
        addData(list);
        // 关闭writer，释放内存
        excelWriter.close();
    }

    /**
     * 对list数据源将其里面的数据导入到excel表单
     *
     * @param list      导出数据集合
     * @param sheetName 工作表的名称
     * @return 结果
     */
    public void exportExcel(HttpServletResponse response,List<T> list, String sheetName, List<String> useFieldList) {
        try {
            this.excelWriter = cn.hutool.poi.excel.ExcelUtil.getWriter("D:/YanWe/Desktop/新建文件夹/" + DateUtil.format(DateUtil.date(), "HHmmss") + ".xlsx");
            excelWriter.renameSheet(sheetName);

            //初始化参数
            initData(useFieldList);
            //设置标题
//            setTitle(sheetName);
            //设置头部
            setHeader();
            //设置数据
            addData(list);

            excelWriter.flush(response.getOutputStream(), true);
            // 关闭writer，释放内存
            excelWriter.close();
        } catch (Exception ex) {

        } finally {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=test.xlsx");
        }
    }

    public List<T> importExcel(InputStream inputStream) {
        ExcelReader excelReader = ExcelUtil.getReader(inputStream);
        //初始化
        initData(Arrays.asList());
        for (int i = 0; i < fieldColumnList.size(); i++) {
            Pair<String, ExcelColumn> fieldModel = fieldColumnList.get(i);
            ExcelColumn excelColumn = fieldModel.getValue();
            excelReader.addHeaderAlias(StrUtil.isBlank(excelColumn.name()) ? fieldModel.getKey() : excelColumn.name(),fieldModel.getKey());
        }
        return excelReader.readAll(clazz);
    }

    public void init() {
//        initData();
//        //设置标题
//        setTitle(this.sheetName);
//        //设置头部
//        setHeader();
//        //设置数据
//        addData();
    }

    private GzExcelUtil setTitle(String sheetName) {
        excelWriter.merge(fieldColumnList.size() - 1, sheetName);
        CellStyle style = getDefaultStyle();
        style.setFillForegroundColor(excelTable.titleBackgroundColor().index);
        Font font = getDefaultFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 16);
        font.setColor(excelTable.titleColor().index);
        style.setFont(font);
        excelWriter.setRowStyleIfHasData(excelWriter.getCurrentRow() - 1, style);
        excelWriter.setRowHeight(excelWriter.getCurrentRow() - 1, excelTable.titleHeight());
        return this;
    }

    /**
     * 设置行标题
     */
    private GzExcelUtil setHeader() {
        excelWriter.writeHeadRow(fieldColumnList.stream().map(item -> StrUtil.isBlank(item.getValue().name()) ? item.getKey() : item.getValue().name()).collect(Collectors.toList()));
        for (int i = 0; i < fieldColumnList.size(); i++) {
            Pair<String, ExcelColumn> fieldModel = fieldColumnList.get(i);
            ExcelColumn excelColumn = fieldModel.getValue();
            excelWriter.addHeaderAlias(fieldModel.getKey(), StrUtil.isBlank(excelColumn.name()) ? fieldModel.getKey() : excelColumn.name());
            excelWriter.setColumnWidth(i, excelColumn.width());

            CellStyle style = getDefaultStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setFillForegroundColor(excelColumn.headerBackgroundColor().index);
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = getDefaultFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 10);
            font.setColor(excelColumn.headerColor().index);
            style.setFont(font);
            excelWriter.setRowStyleIfHasData(excelWriter.getCurrentRow() - 1, style);
        }

        excelWriter.setRowHeight(excelWriter.getCurrentRow() - 1, excelTable.headerHeight());
        return this;
    }

    /**
     * 设置行
     */
    public void addData(List<T> list) {
        int rowCount = excelWriter.getRowCount();
        excelWriter.write(list);
        for (int i = 0; i < fieldColumnList.size(); i++) {
            ExcelColumn excelColumn = fieldColumnList.get(i).getValue();
            CellStyle style = getDefaultStyle();
            style.setAlignment(excelColumn.align());
            style.setFillForegroundColor(excelColumn.backgroundColor().index);
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = getDefaultFont();
            font.setBold(false);
            font.setFontHeightInPoints((short) 10);
            font.setColor(excelColumn.color().index);
            style.setFont(font);
            excelWriter.setColumnStyleIfHasData(i, rowCount, style);
        }
        for (int i = 0; i < list.size(); i++) {
            excelWriter.setRowHeight(rowCount + i, excelTable.dataHeight());
        }
    }

    /**
     * 初始化注解
     */
    private void initData(List<String> useFieldList) {
        for (Field field : ReflectUtil.getFields(clazz)) {
            if (AnnotationUtil.hasAnnotation(field, ExcelColumn.class)) {
                String fieldName = ReflectUtil.getFieldName(field);
                ExcelColumn excelColumn = AnnotationUtil.getAnnotation(field, ExcelColumn.class);
                if (CollUtil.isEmpty(useFieldList)) {
                    fieldColumnList.add(new Pair(fieldName, excelColumn));
                } else if (!useFieldList.contains(useFieldList.contains(field.getName()))) {
                    fieldColumnList.add(new Pair(fieldName, excelColumn));
                }
            }
            //设置头部注解
            if (AnnotationUtil.hasAnnotation(ExcelTestModel.class, ExcelTable.class)) {
                excelTable = AnnotationUtil.getAnnotation(ExcelTestModel.class, ExcelTable.class);
            }
        }
    }

    /**
     * 获取默认样式
     *
     * @return
     */
    private CellStyle getDefaultStyle() {
        CellStyle style = excelWriter.createCellStyle();
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        return style;
    }

    /**
     * 获取默认字体
     *
     * @return
     */
    private Font getDefaultFont() {
        Font font = excelWriter.createFont();
        font.setFontName("Arial");
        font.setFontHeightInPoints((short) excelTable.dataHeight());
        font.setBold(false);
        font.setColor(IndexedColors.BLACK.index);
        return font;
    }

    public void importTemplateExcel(HttpServletResponse response, String sheetName) {
        try {
            this.excelWriter = cn.hutool.poi.excel.ExcelUtil.getWriter();
            excelWriter.renameSheet(sheetName);

            //初始化参数
            initData(Arrays.asList());
            //设置标题
//            setTitle(sheetName);
            //设置头部
            setHeader();

            excelWriter.flush(response.getOutputStream(), true);
            // 关闭writer，释放内存
            excelWriter.close();
        } catch (Exception ex) {

        } finally {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=test.xlsx");
        }
    }
}
